﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SolverFoundation.Common;
using Microsoft.SolverFoundation.Services;
using System.IO;

namespace OptimizationChecker
{
    class Program
    {
        static void Main(string[] args)
        {
            SolverContext context = SolverContext.GetContext();
            Model solver = context.CreateModel();
            int i;
            double lo, hi;
            string line;
            string[] lineA, sep;
            StreamReader sr;

            // add variables 
            for (i = 1; i <= 97; i++)
                solver.AddDecision(new Decision(Domain.Real, "q_" + i));

            // read constraints
            sr = new StreamReader(@"..\..\..\..\constraints.txt");
            sep = new string[] {"\t"};
            while (!sr.EndOfStream)
            {
                line = sr.ReadLine();
                lineA = line.Split(sep, StringSplitOptions.None);
                string currname = lineA[0];
                Console.WriteLine("Adding constraint for node " + currname + "...");
                solver.AddConstraint(currname, lineA[1]);
            }
            sr.Close();

            // read bounds
            sr = new StreamReader(@"..\..\..\..\bounds.txt");
            i = 0; 
            while (!sr.EndOfStream)
            {
                i++;
                line = sr.ReadLine();
                lineA = line.Split(sep, StringSplitOptions.None);
                lo = double.Parse(lineA[0]);
                hi = double.Parse(lineA[2]);
                string var = "q_" + i;
                solver.AddConstraint("constraint_lo_" + var, var + " >= " + lo.ToString());
                solver.AddConstraint("constraint_hi_" + var, var + " <= " + hi.ToString());
            }
            sr.Close();

            // initial decisions that should work well
            Decision dec = solver.Decisions.First(d => (d.Name == "q_3"));
            dec.SetInitialValue(0.0);
            dec = solver.Decisions.First(d => (d.Name == "q_4"));
            dec.SetInitialValue(408.235);
            dec = solver.Decisions.First(d => (d.Name == "q_5"));
            dec.SetInitialValue(9774.0);
            dec = solver.Decisions.First(d => (d.Name == "q_7"));
            dec.SetInitialValue(11484.8);

            // add the goal
            solver.AddGoal("MinPowerDiff", GoalKind.Minimize, "1000000 * ((0.001 * (((1.0236967842816 * q_7) * (1910.03774560496 / 2 - 784.275537270087)) * 0.882591376338833) - 1771.7307)^2 + (0.001 * (((1.0236967842816 * q_5) * (2438.04725411333 / 2 - 962.670297604646)) * 0.90581390272424) - 2323.3807)^2 + (166 - (0.001 * (((1.0236967842816 * q_4) * (3137.1484084328 / 2 - (2438.04725411333 / 2))) / 0.88)))^2 + (0.001 * (((1.0236967842816 * q_3) * (3137.1484084328 / 2 - (2438.04725411333 / 2))) * 0.88))^2) + 100000000 * (50000000 * (q_19^2)) + 1000000 * (q_17^2 + q_18^2)");
//            solver.AddGoal("MinPowerDiff", GoalKind.Minimize, "1000000 * ((0.001 * (((1.0236967842816 * q_7) * (1910.03774560496 / 2 - 784.275537270087)) * 0.882591376338833) - 1771.7307)^2 + (0.001 * (((1.0236967842816 * q_5) * (2438.04725411333 / 2 - 962.670297604646)) * 0.90581390272424) - 2323.3807)^2 + (166 - (0.001 * (((1.0236967842816 * q_4) * (3137.1484084328 / 2 - (2438.04725411333 / 2))) / 0.88)))^2 + (0.001 * (((1.0236967842816 * q_3) * (3137.1484084328 / 2 - (2438.04725411333 / 2))) * 0.88))^2) + 100000000 * (50000000 * (q_19^2)) + 1000000 * (q_17^2 + q_18^2) + 0.373195103352528 * (0.001 * (((1.0236967842816 * q_7) * (1910.03774560496 / 2 - 784.275537270087)) * 0.882591376338833)) + 3.13501023232616 * (0.001 * (((1.0236967842816 * q_5) * (2438.04725411333 / 2 - 962.670297604646)) * 0.90581390272424)) + 0.950327342265066 * (0.001 * (((1.0236967842816 * q_4) * (3137.1484084328 / 2 - (2438.04725411333 / 2))) / 0.88)) - (0.0000469136854095814 * (0.001 * (((1.0236967842816 * q_3) * (3137.1484084328 / 2 - (2438.04725411333 / 2))) * 0.88)))");
//            solver.AddGoal("MinPowerDiff", GoalKind.Minimize, "1000000 * ((0.001 * (((1.0236967842816 * q_7) * (1910.03774560496 / 2 - 784.275537270087)) * 0.882591376338833) - 1771.7307)^2 + (0.001 * (((1.0236967842816 * q_5) * (2438.04725411333 / 2 - 962.670297604646)) * 0.90581390272424) - 2323.3807)^2 + (166 - (0.001 * (((1.0236967842816 * q_4) * (3137.1484084328 / 2 - (2438.04725411333 / 2))) / 0.88)))^2 + (0.001 * (((1.0236967842816 * q_3) * (3137.1484084328 / 2 - (2438.04725411333 / 2))) * 0.88))^2) + 100000000 * (50000000 * (q_19^2)) + 1000000 * (q_17^2 + q_18^2) + 0.373195103352528 * (0.001 * (((1.0236967842816 * q_7) * (1910.03774560496 / 2 - 784.275537270087)) * 0.882591376338833)) + 3.13501023232616 * (0.001 * (((1.0236967842816 * q_5) * (2438.04725411333 / 2 - 962.670297604646)) * 0.90581390272424)) + 0.950327342265066 * (0.001 * (((1.0236967842816 * q_4) * (3137.1484084328 / 2 - (2438.04725411333 / 2))) / 0.88)) - (0.0000469136854095814 * (0.001 * (((1.0236967842816 * q_3) * (3137.1484084328 / 2 - (2438.04725411333 / 2))) * 0.88))) + -(49000 * q_38) - (99999999 * q_39) - (49730 * q_41) - (99999999 * q_42) - (49950 * q_44) - (99999999 * q_45) - (49750 * q_47) - (99999999 * q_48) - (49990 * q_50) - (10 * q_51) - (49990 * q_52) - (10 * q_53) - (49980 * q_54) - (99999998 * q_73) + 399999 * q_81 - (1000000 * q_83) - (100000000 * q_84) - (1000000000 * q_85) - (98999999 * q_86) + 399999 * q_87 - (98999999 * q_89) + 399999 * q_90 + 399999 * q_92 + 10 * q_93 + 10 * q_94 + 10 * q_95 + 10 * q_96 + 10 * q_97");
            Solution solution = context.Solve();
        
            // write output
            Console.WriteLine("Power solver solution quality is: " + solution.Quality.ToString());
            Console.WriteLine("Decisions:");
            foreach (Decision d in solution.Decisions)
                Console.WriteLine(d.Name + "\t" + d.ToDouble().ToString());
            Console.WriteLine("Solution report: ");
            Console.WriteLine(solution.GetReport());
        }
    }
}
